<script setup lang="ts">
import vjmap3d, { App, Marker2D } from 'vjmap3d';
import { inject, ref } from 'vue';
import { getEndPoints } from '../lib/util';
import { FrontSide, MeshPhongMaterial, RepeatWrapping } from 'three';
import { texture } from 'three/examples/jsm/nodes/Nodes.js';
const app = inject("app") as App;

// 是否显示人员详细情况
const showPersonDetail = ref(false);
const personId = ref(1);
const personName = ref('人员1');

// app中的data是响应式的。可以通过设置里面的值来进行监听
app.data.showPersonDetail = false;
app.data.personId = 1;
app.data.personName = '人员1';
app.data.personRoutes = [];
// 监听变化值
vjmap3d.reactivity.watch(() => app.data.showPersonDetail, () => {
	showPersonDetail.value = app.data.showPersonDetail;
})
vjmap3d.reactivity.watch(() => app.data.personId, () => {
	personId.value = app.data.personId;
})
vjmap3d.reactivity.watch(() => app.data.personName, () => {
	personName.value = app.data.personName;
})

// 是否正在轨迹回放
const isRoutePlaying = ref(false);
let disposeCb: any;
const playroute = async () => {
	isRoutePlaying.value = !isRoutePlaying.value;
	// 把人员隐藏或显示
	app.data.personMarkerGroupEntity.visible = !isRoutePlaying.value;

	if (isRoutePlaying.value) {
		if (disposeCb) return;
		// 显示路径
		let paths = app.data.personRoutes.map((r: any) => r.posTop.toArray())
	
		disposeCb = showRoute(paths, () => {
			// 动画结束回调
			isRoutePlaying.value = false;
			// 把人员隐藏或显示
			app.data.personMarkerGroupEntity.visible = true;
			disposeCb = null;
		})
	} else {
		// 结束动画
		if (disposeCb) {
			disposeCb();
			disposeCb = null;
		}
	}
	
	
}

const showRoute =  (paths: any, cb: Function) => {
	
	let ent = app.getLoadedResources().cloneModel("person", {
		size: 0.05,
      	splitSubEntity: true
	});
	ent.addTo(app);
	// 右下角显示小地图
    let miniMapControl = new vjmap3d.MiniMapControl({
		followTarget: ent.node,
		// mapSyncRotateZ: true,
		mapSize: 20,
	});
	app.addControl(miniMapControl)
    
	let duration = paths.length * 1000; // 持续时间
	if (duration > 20 * 1000) {
		//  如果时间太长，就强制20s走完
		duration = 20 * 1000;
	}
    let pathAnmiMod = ent.add(vjmap3d.PathAnimateModule)
    pathAnmiMod.start({
        paths: paths,
        cameraFollow: true, 
        // offsetAngle:90,
        //followAngle: 15,
		//followDist: 10,
        animation: {
            duration: duration
        },
        startAimatorClipName: 'Walk',
        stopAimatorClipName: ""
    }).then(() => {
		dispose();
		cb(); //回调
	})

    

	const dispose = () => {
		if (miniMapControl) {
			app.removeControl(miniMapControl);
			pathAnmiMod.tween.runningTween.stop();
			// 移除实体
			ent.remove()
			// @ts-ignore
			miniMapControl = null;
		}
	}

	return dispose;
}


// 是否显示出口路线
const isShowShortestPath = ref(false);
// 显示最近出口路线
const shortestpath = () => {
	if (isShowShortestPath.value) {
		removeShortestPath();
		isShowShortestPath.value = false;
		return;
	}
	isShowShortestPath.value = true;
	if (isRoutePlaying.value) {
		// 如果正在显示历史轨迹，先取消显示
		playroute();
	}
	// 当前点
	let paths = app.data.personRoutes.map((r: any) => r.posTop.toArray())
	// 计算管道实体中所有的出口位置坐标
	let endpoints = getEndPoints(app.data.tubeEntity);
	//console.log(endpoints)
	let personPoint = paths[paths.length - 1]; // 取最后一个

	// 查找距哪个出口近
	let results = endpoints.map(endpt => {
		let sp = vjmap3d.findShortestPath(personPoint, endpt,
			app.data.tubeEntity.inputData.map((d: any) => ({
				points: d.paths
			}))
		)
		return {
			point: endpt,
			distance: vjmap3d.lineDistance(sp.route ?? [])
		}
	})
	// 按结果的路径距离排序
	results.sort((a, b) => a.distance - b.distance)
	showShortPath(personPoint, results[0].point)
}


let outMaterialShortestPath: any;
let tubeShortestPath: any;
let startMarker2d: Marker2D, endMarker2d: Marker2D;
const showShortPath = (startPoint: any, endPoint: any) => {
    removeShortestPath();

	startMarker2d = new vjmap3d.Marker2D({
        color: 'red',
        allowOverlap: true
    });
    startMarker2d.setPosition(startPoint);
    startMarker2d.addTo(app);

	endMarker2d = new vjmap3d.Marker2D({
        color: 'green',
        allowOverlap: true
    });
    endMarker2d.setPosition(endPoint);
    endMarker2d.addTo(app);

    if (!outMaterialShortestPath) {
        // 创建一个最短路径高亮的材质
        outMaterialShortestPath = new MeshPhongMaterial({
            color: 0xffff00,
            side: FrontSide
        });
    }

    let sp = vjmap3d.findShortestPath(startPoint, endPoint,
		app.data.tubeEntity.inputData.map((d: any) => ({
            points: d.paths
        }))
    );
  
    let opts = {
        data: [
            {
                paths: sp.route,
                name: "path1"
            }
        ],
        nodeRadius: 0.5,
        outerMaterial: outMaterialShortestPath,
        // 断面比原来的稍大点
        sect: {
            shape: "arch",
            rectWidth: 1.2,
            rectHeight: 0.6
        },
        /** 建立拓扑关系策略（默认nodeIntersect） nodeIntersect 一条管道的始末节点与另一条相交时，自动把另一条拆成多段建立拓扑。nodeEqual 一条管道的始末节点与另一条管道的始末节点相等时建立拓扑，不会自动拆分 */
        topoStrategy: "nodeEqual"
    }
	// @ts-ignore
    tubeShortestPath = new vjmap3d.PathTubeEntities(opts);
    tubeShortestPath.addTo(app);
}

// 移除最短路径
const removeShortestPath = () => {
    if (startMarker2d) {
        startMarker2d.remove();
		// @ts-ignore
        startMarker2d = null;
    }
    if (endMarker2d) {
        endMarker2d.remove();
		// @ts-ignore
        endMarker2d = null;
    }
    if (tubeShortestPath) {
        tubeShortestPath.remove();
        tubeShortestPath = null;
    }
   
}

</script>

<template>
   <div class="personpanel" v-if="showPersonDetail">
      <div class="seHeader">
        <span>
          <p class="p-1">人员详细情况</p>
          <a class="p-2" @click="playroute">{{ isRoutePlaying ? "退出轨迹回放" : "查看人员轨迹回放" }}</a>
		  <a class="p-3" @click="shortestpath">{{ isShowShortestPath ? "删除出口路线" : "最近出口路线" }}</a>
        </span>
        <span></span>
      </div>
	  
      <div class="serData">
        <div class="serDataLeft">
          <div><span class="serNum">{{personId}}</span></div>
          <p>人员编号</p>
        </div>
        <div class="serDataLeft">
          <div><span class="serNum">{{personName}}</span></div>
          <p>人员姓名</p>
        </div>
      </div>
    </div>
</template>

<style scoped>
   
.personpanel {
    position: absolute;
	width: 500px;
	height: 205px;
    left: 10px;
    top: 100px;
	background: url(./img/k_2.png);
    background-size: cover;
	margin-top: 20px;
}
.seHeader {
	padding-top: 18px;
	overflow: hidden;
}
.seHeader span:first-child {
	float: left;
	margin-left: 29px;
	margin-top: 8px;
}
.seHeader span:first-child .p-1 {
	font-size: 20px;
	color: #fff;
}
.seHeader span:first-child .p-2 {
	font-size: 25px;
	color: #09f1ca;
	margin-left: 20px;
	cursor: pointer;
	text-decoration: underline
}
.seHeader span:first-child .p-3 {
	font-size: 25px;
	color: #09f1ca;
	margin-left: 60px;
	cursor: pointer;
	text-decoration: underline
}
.seHeader span:last-child {
 	float: right;
 	font-size: 46px;
 	color: #7bb9ff;
 	margin-right: 28px;
 }
 
.serData {
	margin-top: 7px;
	overflow: hidden;
	color: #66dffb;
}
.serData > div {
	float: left;
	font-size: 18px;
	text-align:  center;
}
.serData > .serDataLeft {
	margin-left: 15%;
	padding: 0 12px;
}
.serDataLeft .serNum {
	font-size: 60px;
	color: #f0bd54;
}

</style>